package com.zzyl.serve.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baidubce.qianfan.model.BaseResponse;
import com.baidubce.qianfan.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.huaweicloud.sdk.iotda.v5.IoTDAAsyncClient;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.RedisKeyConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.serve.dto.DeviceDto;
import com.zzyl.serve.vo.DeviceDetailVo;
import com.zzyl.serve.vo.ProductVo;
import org.bouncycastle.pqc.legacy.math.linearalgebra.PolynomialRingGF2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.serve.mapper.DeviceMapper;
import com.zzyl.serve.domain.Device;
import com.zzyl.serve.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 设备管理Service业务层处理
 * 
 * @author koi
 * @date 2025-05-10
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService
{
    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 查询设备管理
     * 
     * @param id 设备管理主键
     * @return 设备管理
     */
//    @Override
//    public Device selectDeviceById(Long id)
//    {
//        return getById(id);
//    }

    /**
     * 查询设备管理列表
     * 
     * @param device 设备管理
     * @return 设备管理
     */
    @Override
    public List<Device> selectDeviceList(Device device)
    {
        return deviceMapper.selectDeviceList(device);
    }

    /**
     * 新增设备管理
     * 
     * @param device 设备管理
     * @return 结果
     */
    @Override
    public int insertDevice(Device device)
    {
        return save(device) ? 1 : 0;
    }

    /**
     * 修改设备管理
     * 
     * @param device 设备管理
     * @return 结果
     */
    @Override
    public int updateDevice(Device device)
    {
        return updateById(device) ? 1 : 0;
    }

    /**
     * 批量删除设备管理
     * 
     * @param ids 需要删除的设备管理主键
     * @return 结果
     */
    @Override
    public int deleteDeviceByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除设备管理信息
     * 
     * @param id 设备管理主键
     * @return 结果
     */
    @Override
    public int deleteDeviceById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IoTDAClient client;
    @Override
    public void syncProductList() {

        ListProductsRequest request = new ListProductsRequest();
        request.setLimit(50);
        ListProductsResponse response =client.listProducts(request);

        List<ProductSummary> productList = response.getProducts();

        redisTemplate.opsForValue().set(RedisKeyConstants.IOT_ALL_PRODUCT_LIST, productList);
    }

    @Override
    public List<ProductVo> allProduct() {

        //1.从redis查询产品信息
        List<ProductSummary>productList = (List<ProductSummary>)redisTemplate.opsForValue().get(RedisKeyConstants.IOT_ALL_PRODUCT_LIST);

        //2.封装前端需要的vo
        if(ObjectUtils.isEmpty(productList)){
            return CollectionUtil.empty(List.class);
        }
        //注意list拷贝选择copyTolist
        List<ProductVo> volist = BeanUtil.copyToList(productList, ProductVo.class);
        return volist;
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //1.判断设备名称name是否重复，（如果重复，抛出异常，终止运行）
        long countName = count(
                new LambdaQueryWrapper<Device>()
                        .eq(StrUtil.isNotBlank(deviceDto.getDeviceName()),Device::getDeviceName,deviceDto.getDeviceName())
                //      .eq(StrUtil.isNotBlank(dto.getDeviceName()), Device::getDeviceName, dto.getDeviceName())
        );
        if(countName>0){
            throw new RuntimeException("设备名称重复了");
        }
        //2.校验设备标识码nodeId是否重复
        long countNodeId = count(
                new LambdaQueryWrapper<Device>()
                        .eq(StrUtil.isNotBlank(deviceDto.getNodeId()),Device::getNodeId,deviceDto.getNodeId())
        );
        if(countNodeId>0){
            throw new RuntimeException("设备标识码重复了");
        }
        //3.校验同一位置（位置类型+绑定为位置）是否绑定了同一类产品（产品唯一标识）
        long countProduct =count(
                new LambdaQueryWrapper<Device>()
                        .eq(Device::getLocationType,deviceDto.getLocationType())
                        .eq(Device::getBindingLocation,deviceDto.getBindingLocation())
                        .eq(Device::getPhysicalLocationType,deviceDto.getPhysicalLocationType())
                        .eq(Device::getProductKey,deviceDto.getProductKey())
        );
        if (countProduct>0){
            throw new RuntimeException("同一个位置已绑定同一类产品");
        }
        //4.在iot平台中新增设备
        AddDeviceRequest request = new AddDeviceRequest();
        AddDevice body = new AddDevice();
        body.setProductId(deviceDto.getProductKey());
        body.setDeviceName(deviceDto.getDeviceName());
        body.setNodeId(deviceDto.getNodeId());
        //设置设备的密钥
        String scret  = UUID.randomUUID().toString().replaceAll("-", "");
        AuthInfo authInfo = new AuthInfo();
        authInfo.setSecret(scret);
        body.setAuthInfo(authInfo);
        request.withBody(body);

        //发送请求
//        AddDeviceResponse response = client.addDevice(request);
//        if(request.getStatus().equals("201")){
//            //如果异常，则抛出异常，终止运行
//            throw new RuntimeException("设备注册失败");
//        }
        String iotId ="";
        try{
            AddDeviceResponse response = client.addDevice(request);
            iotId = response.getDeviceId();
        } catch (Exception e) {
            //抛出异常，终止运行
           throw new RuntimeException("设备注册失败");
           // e.printStackTrace();
        }
        //5.设备数据保存到数据库
        //对象属性拷贝
        Device device =BeanUtil.toBean(deviceDto,Device.class);
        device.setIotId(iotId);
        device.setSecret(scret);
        //保存到数据库
        save(device);
    }

    /**
     * 设备详情
     * @param iotId
     * @return
     */

    @Override
    public DeviceDetailVo showDeviceInfo(String iotId) {
        //1.先查询IOT平台，得到设备详情：设备状态、激活时间
        ShowDeviceRequest  request = new ShowDeviceRequest();
        request.withDeviceId(iotId);

        String activeTimeStr = "";
        String deviceStatus = "";
        try {
            ShowDeviceResponse response = client.showDevice(request);
            //设备状态、激活时间
            deviceStatus = response.getStatus();
            activeTimeStr = response.getActiveTime();
        }catch (Exception e){
            //如果有异常，终止运行
            e.printStackTrace();
            throw new RuntimeException("查询设备详情失败");
        }
        //2.再查数据库设备表，得到设备详情
        Device device = getOne(
                new LambdaQueryWrapper<Device>()
                        .eq(Device::getIotId, iotId)
        );
        //3.组装VO返回
        DeviceDetailVo vo = BeanUtil.toBean(device, DeviceDetailVo.class);
        vo.setDeviceStatus(deviceStatus);

        //需要单独组装时间
        if(StringUtils.isNotEmpty(activeTimeStr)){
            LocalDateTime activeTime = LocalDateTimeUtil.parse(activeTimeStr, DatePattern.UTC_MS_PATTERN);
            //日期时间转换
            activeTime = activeTime.atZone(ZoneId.from(ZoneOffset.UTC))
                    .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                    .toLocalDateTime();
            vo.setActiveTime(activeTime);
        }
        return vo;
    }



    @Override
    public List<Map> queryServiceProperties(String iotId) {
        //1.先查询IOT平台，得到设备最新上报数据
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.withDeviceId(iotId);
        try{
            ShowDeviceShadowResponse response = client.showDeviceShadow(request);
            //2.解析响应数据
            Object properties = response.getShadow()
                    .get(0)
                    .getReported()
                    .getProperties();
                    //json对象转换为map
            JSONObject jsonObject = JSONUtil.parseObj(properties);
            //上报时间
            String eventTimeStr = response.getShadow().get(0).getReported().getEventTime();

            //3.封装数据
            List list = new ArrayList();
            //需要对日期格式进行单独处理
            //处理上报时间日期
            LocalDateTime activeTime = LocalDateTimeUtil.parse(eventTimeStr, "yyyyMMdd'T'HHmmss'Z'");
            //日期时区转换
            LocalDateTime evenTime = activeTime.atZone(ZoneId.from(ZoneOffset.UTC))
                    .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                    .toLocalDateTime();

            jsonObject.forEach((key, value) -> {
                Map<String, Object> map = new HashMap<>();
                map.put("functionId",key);
                map.put("value",value);
                map.put("eventTime", evenTime);
                list.add(map);
            });
         return list;
        } catch (Exception e) {
            //如果有异常，则终止运行
            e.printStackTrace();
            throw new BaseException("调用失败");
        }

    }


}
